package drds.plus.sql_process.abstract_syntax_tree.node;

import drds.plus.common.jdbc.Parameters;
import drds.plus.sql_process.abstract_syntax_tree.execute_plan.ExecutePlan;
import drds.plus.sql_process.abstract_syntax_tree.expression.item.function.Function;
import drds.plus.sql_process.optimizer.chooser.share_delegate.ShareDelegateAnnotation;
import lombok.Getter;
import lombok.Setter;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;


public abstract class Node<T extends Node> implements Comparable {
    @Setter
    @Getter
    protected boolean broadcast = false; // 是否为广播表
    @Setter
    @Getter
    protected String sql;
    @Setter
    @Getter
    protected boolean existSequenceValue = false; // 是否存在sequence
    @Setter
    @Getter
    private List<String> dataNodeIdList = new ArrayList<String>(); // 数据处理节点,比如groupName
    @Setter
    @Getter
    private List<Object> extras = new ArrayList<Object>(); // 比如唯一标识，joinMergeJoin中使用

    public Node() {

    }

    /**
     * <pre>
     * 1. 结合table meta信息构建结构树中完整的column字段
     * 2. 处理join/merge的下推处理
     * </pre>
     */
    public abstract void build();

    /**
     * 需要预先执行build.构造执行计划
     */
    @ShareDelegateAnnotation
    public ExecutePlan toExecutePlan() {
        return toExecutePlan(0);
    }

    /**
     * 需要预先执行build.构造执行计划
     */
    public abstract ExecutePlan toExecutePlan(int shareIndex);

    /**
     * 处理bind val
     */
    public abstract void assignment(Parameters parameters);

    public abstract boolean isNeedBuild();

    @ShareDelegateAnnotation
    public String getDataNodeId() {
        return getDataNodeId(0);
    }

    @ShareDelegateAnnotation
    public void setDataNodeId(String dataNode) {
        setDataNodeId(0, dataNode);
    }

    public String getDataNodeId(int shareIndex) {
        ensureCapacity(dataNodeIdList, shareIndex);
        return dataNodeIdList.get(shareIndex);
    }

    public void setDataNodeId(int shareIndex, String dataNodeId) {
        ensureCapacity(dataNodeIdList, shareIndex);
        this.dataNodeIdList.set(shareIndex, dataNodeId);

    }

    @ShareDelegateAnnotation
    public Object getExtra() {
        return getExtra(0);
    }

    @ShareDelegateAnnotation
    public void setExtra(Object obj) {
        setExtra(0, obj);
    }

    public Object getExtra(int shareIndex) {
        ensureCapacity(extras, shareIndex);
        return this.extras.get(shareIndex);
    }

    public void setExtra(int shareIndex, Object obj) {
        ensureCapacity(extras, shareIndex);
        this.extras.set(shareIndex, obj);

    }

    public int compareTo(Object arg) {
        // 主要是将自己包装为Comparable对象，可以和Number/string类型具有相同的父类，构建嵌套的查询树
        throw new UnsupportedOperationException();
    }


    public boolean isShareNode() {
        return dataNodeIdList.size() > 1;
    }

    public int getShareSize() {
        return dataNodeIdList.size();
    }

    public void ensureCapacity(Collection collection, int minCapacity) {
        while (collection.size() <= minCapacity) {
            collection.add(null);
        }
    }


    /**
     * 获取对应的subquery filter,不包括correlate subquery
     */
    public abstract Function getNextSubQueryFunction();

    // ----------------- 复制 ----------------

    /**
     * 复制当前节点和子节点，属性信息不做递归复制
     */
    public abstract T copy();

    /**
     * 只复制当前节点，不复制子节点
     */
    public abstract T copySelf();

    /**
     * 复制当前节点和子节点，属性信息进行递归复制
     */
    public abstract T deepCopy();
}
